#include "export.h"
#include "global.h"

#include <QFile>

unsigned char netidx;

void ExportNetlist::save_netlist(QList<FuncBlockBase*> *fbList, QList<WireBase*> *wireList, QList<PinBase*> *pinList)
{
    FuncBlockBase *fb;
    PinFB *pin;

    netidx = NETIDX_FIRST_FREE;

    for (int i=0; i<fbList->count(); i++)
        fbList->at(i)->resetMemoryFlagIdx();
    for (int p=0; p<pinList->count(); p++)
        pinList->at(p)->resetMemoryFlagIdx();

    try
    {
        for (int i=0; i<fbList->count(); i++)
        {
            fb = fbList->at(i);
            for (int p=0; p<fb->getPinCount(); p++)
            {
                pin = fb->getPinRef(p);
                if (pin->getDirection() == dirOutput)
                {
                    if (pin->getRefCount() > 0)
                    {
                        pin->setMemoryFlagIdx(netidx);
                        netidx++;
                        setWirePathMemoryFlags(pin);
                    }
                }
            }
        }
    }
    catch (LoopException le)
    {
        qDebug() << "LoopException";
    }

    QFile netFile("netlist.txt");
    if (netFile.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        QTextStream out(&netFile);

        for (int i=0; i<fbList->count(); i++)
        {
            out << "#" << fbList->at(i)->objectName() << endl;
            fb = fbList->at(i);
            for (int c=0; c<fb->getConfigCount(); c++)
            {
                ConfigBase *cb = fb->getConfigRef(c);
                if (cb->type == ctUnknown)
                    out << "FF";
                else if (cb->type == ctConst)
                    out << QString().setNum(cb->value, 16);
                else if (cb->type == ctNetPin)
                {
                    PinBase *pin = fb->getPinRefByNo(cb->value);
                    out << pin->getMemoryFlagIdx();
                }
                else if (cb->type == ctParam)
                {
                    ParamBase *param = fb->getParamById(cb->value);
                    out << param->value;
                }
                else if (cb->type == ctChecksum)
                {
                    out << "CC";
                }
                if (c < fb->getConfigCount()-1)
                    out << ":";
            }
            /*
            out << "#" << fbList->at(i)->objectName() << endl;
            out << "### ";
            for (int p=0; p<fb->getPinCount(); p++)
            {
                PinBase *pin = fb->getPinRef(p);
                out << pin->getMemoryFlagIdx() << " ";
            }
            */
            out << endl;
        }
    }
    netFile.close();
}

void ExportNetlist::setWirePathMemoryFlags(PinBase *pin)
{
    WireBase *wire;
    PinBase *other_pin;

    for (int w=0; w<pin->getRefCount(); w++)
    {
        wire = pin->getRefWire(w);
        other_pin = ((wire->startPin == pin) ? wire->endPin : wire->startPin);
        if (other_pin->getParent()->objectName() != "SchematicBase")
        {
            PinFB *fbpin = (PinFB*)other_pin;
            if (fbpin->getDirection() != dirInput)
            {
                qDebug() << "WireDriversException" << other_pin->getParent()->objectName() << other_pin->getMemoryFlagIdx();
                throw WireDriversException();
            }
            else
                other_pin->setMemoryFlagIdx(pin->getMemoryFlagIdx());
        }
        else if (other_pin->getMemoryFlagIdx() == NETIDX_NOT_CONNECTED) // noch Frei, sonst Schleife in der Schematic und Endlosschleife hier
        {
            other_pin->setMemoryFlagIdx(pin->getMemoryFlagIdx());
            setWirePathMemoryFlags(other_pin);
        }
        else
        {
            qDebug() << "LoopException" << other_pin->getMemoryFlagIdx();
            throw LoopException();
        }
    }
}
